Skip to content

feat(napi): add RwSite.listPages() enumerating pages with titles#579

Merged
yumike merged 1 commit into
mainfrom
feat/list-pages-576
Jun 24, 2026
Merged

feat(napi): add RwSite.listPages() enumerating pages with titles#579
yumike merged 1 commit into
mainfrom
feat/list-pages-576

Conversation

@yumike

@yumike yumike commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Closes #576.

Summary

Adds a reload-aware napi method that enumerates every page in a site, each with its title and its (sectionRef, subpath) key — the same pair the comment system uses as a page's document_id:

RwSite.listPages(): Promise<Array<{ sectionRef: string; subpath: string; title: string }>>

Motivation

The Backstage doc-comment inbox (rwdocs/backstage-plugins) wants to show a human page title instead of a raw path slug, and caches titles for all pages per site (rebuilt on the ownership-rebuild schedule, when each site is already loaded in memory). It needs to enumerate every page with its title in one cheap pass. The existing surface can't: listSections() enumerates sections (no title), and renderPage() does a full render (Kroki, etc.) — far too costly per page. Resolving titles at serve time is also too expensive (the S3-mode Hub LRU-caches ~20 sites, so a broad inbox would force repeated site loads).

Implementation

A direct three-layer mirror of the existing listSections():

  • SiteState::list_pages() — walks SiteState.pages, computes each page's (section_ref, subpath) via the existing section_location seam, reads Page.title, sorts by (section_ref, subpath). New public PageEntry struct.
  • Site::list_pages()reload_if_needed()? then delegates (mirrors Site::list_sections).
  • napi listPages()spawn_blocking wrapper; new PageEntryResponse; regenerated index.d.ts.

Naming

The enumerated entity is a Page (matches Page / renderPage / SiteState.pages and parallels the sibling listSections/Section), and the set includes virtual directory pages that aren't comment "documents" — so listPages/PageEntry is the accurate, codebase-consistent name. The (sectionRef, subpath) key is still a page's comment document_id. (The issue proposed listDocuments; renamed to listPages after review.)

Scope

Every page is included — the root page (empty subpath) and virtual directory pages — so any comment ever keyed to one still resolves a title. Fields are intentionally minimal (sectionRef, subpath, title); path/ancestors/order are omitted and can be added additively later.

Testing

  • 5 SiteState::list_pages unit tests (root, nested-in-section, outside-any-section, virtual page, page_path_for round-trip, sort order) + 1 Site::list_pages integration test.
  • Full rw-site suite green (150 unit + 4 doctests); rw-napi builds clean; index.d.ts regenerated to listPages(): Promise<Array<PageEntryResponse>>.

🤖 Generated with Claude Code

Closes #576.

Add a reload-aware napi method that enumerates every page in a site, each
with its title and its (sectionRef, subpath) key — the same pair the comment
system uses as a page's document_id. This lets a host (the Backstage
doc-comment inbox) cache human-readable page titles in one cheap pass when a
site is already loaded, instead of N+1 per-page renderPage() calls or repeated
S3 site loads at serve time.

Implemented as a direct three-layer mirror of the existing listSections():
- SiteState::list_pages() walks SiteState.pages, computes each page's
  (section_ref, subpath) via the existing section_location seam, reads the
  title, and sorts by (section_ref, subpath). New public PageEntry struct.
- Site::list_pages() reloads-if-needed then delegates (mirrors list_sections).
- napi listPages() wraps it in spawn_blocking; new PageEntryResponse type;
  regenerated index.d.ts -> listPages(): Promise<Array<PageEntryResponse>>.

Every page is included — the root page (empty subpath) and virtual directory
pages — so any comment keyed to one still resolves a title. Fields are
intentionally minimal (sectionRef, subpath, title); path/ancestors/order are
omitted and can be added additively later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yumike yumike merged commit f566640 into main Jun 24, 2026
18 checks passed
@yumike yumike deleted the feat/list-pages-576 branch June 24, 2026 04:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose all documents via napi: RwSite.listDocuments() with titles

1 participant